#pragma once
#include <iostream>
#include <string>
#include <time.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdarg.h>
#include <stdio.h>
#include <pthread.h>
#include "lockgroup.hpp"

using namespace std;

bool g_issave = false;
#define filename "log.txt"


pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
enum Level
{
    DEBUG = 0,
    INFO,
    WARNING,
    ERROR,
    FATAL
};

string GetLevel(int level)
{
    switch (level)
    {
    case 0:
        return "DEBUG";
    case 1:
        return "INFO";
    case 2:
        return "WARNING";
    case 3:
        return "ERROR";
    case 4:
        return "FATAL";
    default:
        return "NONE";
    }
}
string GetTime()
{
    char buffer[1024];

    time_t t = time(nullptr);
    struct tm *tm = localtime(&t);

    snprintf(buffer, sizeof(buffer), "%d-%d-%d %d:%d:%d",
             tm->tm_year + 1900,
             tm->tm_mon + 1,
             tm->tm_mday,
             tm->tm_hour,
             tm->tm_min,
             tm->tm_sec);

    return buffer;
}
void PrinttoFile(string message)
{
    FILE *f = fopen(filename, "a");
    //fwrite(message.c_str(), sizeof(char), sizeof(message), f);
    fprintf(f,"%s",message.c_str());

    fclose(f);
}

string Logstring(string name, int line, int level, bool issave, const char *format, ...)
{
    string levelstr = GetLevel(level);
    string timestr = GetTime();
    pid_t selfid = getpid();

    va_list arg;
    va_start(arg, format);

    char buffer[1024];
    vsnprintf(buffer, sizeof(buffer), format, arg);

    va_end(arg);

    lockgroup lock(mutex);
    std::string message = "[" + timestr + "]" + "[" + levelstr + "]" +
                          "[" + std::to_string(selfid) + "]" +
                          "[" + name + "]" + "[" + std::to_string(line) + "] " + buffer + "\n";
    if (issave == false)
        cout << message << endl;
    else
        PrinttoFile(message);
    return message;
}

// C99新特性__VA_ARGS__
#define LOG(level,format, ...)                                          \
do                                                                       \
{                                                                        \
    Logstring(__FILE__, __LINE__, level, g_issave, format, ##__VA_ARGS__);\
} while (0)                                                               

#define EnableFile()                \
    do                              \
    {                               \
        g_issave = true;            \
    }while (0)

#define EnableCout()                \
    do                              \
    {                               \
        g_issave = false;           \
    } while (0)                     
